﻿using System;
using System.Data.Entity;
using System.Data.Entity.Validation;
using TinyCms.Core.Repositories;

namespace TinyCms.Domain.Repositories
{
    /// <summary>
    /// 仓储上下文的Entity Framework框架实现
    /// </summary>
    /// <typeparam name="TContext"></typeparam>
    public class EntityFrameworkRepositoryContext<TContext> : RepositoryContext, IEntityFrameworkRepositoryContext
        where TContext:DbContext,new()
    {
        private readonly TContext _ctx = new TContext();
        private readonly object _sync = new object();

        public override void RegisterDeleted<T>(T obj)
        {
            _ctx.Entry(obj).State = System.Data.EntityState.Deleted;
            Committed = false;
        }

        public override void RegisterModified<T>(T obj)
        {
            _ctx.Entry(obj).State = System.Data.EntityState.Modified;
            Committed = false;
        }

        public override void RegisterNew<T>(T obj)
        {
            _ctx.Entry(obj).State = System.Data.EntityState.Added;
            Committed = false;
        }

        public override void Commit()
        {
            if (!Committed)
            {
                lock (_sync)
                {
                    try
                    {
                        _ctx.SaveChanges();
                        Committed = true;
                    }
                    catch (DbEntityValidationException e)
                    {
                        foreach (var eve in e.EntityValidationErrors)
                        {
                            Console.WriteLine("Entity of type \"{0}\" in state \"{1}\" has the following validation errors:",
                                eve.Entry.Entity.GetType().Name, eve.Entry.State);
                            foreach (var ve in eve.ValidationErrors)
                            {
                                Console.WriteLine("- Property: \"{0}\", Error: \"{1}\"",
                                    ve.PropertyName, ve.ErrorMessage);
                            }
                        }
                        throw;
                    }
                }
            }
        }

        public override void Rollback()
        {
            Committed = false;
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (!Committed)
                    Commit();
                _ctx.Dispose();
            }
        }

        #region IEntityFrameworkRepositoryContext Members

        public DbContext Context
        {
            get { return _ctx; }
        }

        #endregion
    }
}
